package gui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;

import javax.swing.JComponent;
import javax.swing.JFrame;

import app.Board;

public class HungarianRingsComponent
extends JComponent
{
    
    /**
     * sh!tty serialization ... -_-
     */
    private static final long serialVersionUID = 1L;
    
    private Board             board;
    private boolean           debug            = false;
    
    public HungarianRingsComponent(Board board)
    {
        super();
        this.board = board;
    }
    
    @Override
    public void paint(Graphics g)
    {
        Graphics2D g2d = (Graphics2D) g;
        // fill white
        g2d.setColor(Color.WHITE);
        g2d.fillRect(0, 0, getWidth(), getHeight());
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
        
        // get the wanted coordinates
        
        // the ring's height/width ratio
        /*
         * The intersection angle of the 2 circles is 5/20 * 2Pi = 5Pi/10. So the angle of the line between the center
         * of a circle and the X axis is 5Pi/20.
         */
        double cutRadiusToNormalRadiusRatio = 1.0 * Math.cos(5 * Math.PI / 20.0);
        double ratio = 1.0 + cutRadiusToNormalRadiusRatio;
        
        double maxCircleRadius = Math.min(getHeight(), getWidth() / ratio) / 2.0;
        double perimeter = maxCircleRadius * Math.PI * 2.0;
        double margin = perimeter / 20.0 / 2.0;
        double circleRadius = maxCircleRadius - margin;
        double ballSize = circleRadius * Math.PI / 10.0;
        
        // draw the 2 main circles
        int xStart = (int) (margin);
        int yStart = (int) (margin);
        
        if (debug)
        {
            drawDebugMainCircles(g2d, cutRadiusToNormalRadiusRatio, maxCircleRadius, circleRadius, xStart, yStart);
        }
        
        // draw the balls
        double firstCircleCenterX = margin + circleRadius;
        double firstCircleCenterY = margin + circleRadius;
        
        // drawing the L list
        for (int i = 3; i < 17; ++i)
        {
            g2d.setColor(board.getLeftBalls().get(i - 3).getBallColor().color);
            int size = (int) ballSize;
            int x = (int) (firstCircleCenterX + circleRadius * Math.cos(Math.PI * 2.0 * i / 20.0 + Math.PI / 20.0))
            - size / 2;
            int y = (int) (firstCircleCenterY + circleRadius * Math.sin(Math.PI * 2.0 * i / 20.0 + Math.PI / 20.0))
            - size / 2;
            g2d.fillOval(x, y, size, size);
        }
        
        // drawing the Ct
        {
            g2d.setColor(board.getTopCentralBall().getBallColor().color);
            int size = (int) ballSize;
            int x = (int) (firstCircleCenterX + circleRadius * Math.cos(Math.PI * 2.0 * 17 / 20.0 + Math.PI / 20.0))
            - size / 2;
            int y = (int) (firstCircleCenterY + circleRadius * Math.sin(Math.PI * 2.0 * 17 / 20.0 + Math.PI / 20.0))
            - size / 2;
            g2d.fillOval(x, y, size, size);
        }
        
        // drawing the r list
        for (int i = 18; i < 22; ++i)
        {
            g2d.setColor(board.getCenterRightBalls().get(i - 18).getBallColor().color);
            int size = (int) ballSize;
            int x = (int) (firstCircleCenterX + circleRadius * Math.cos(Math.PI * 2.0 * i / 20.0 + Math.PI / 20.0))
            - size / 2;
            int y = (int) (firstCircleCenterY + circleRadius * Math.sin(Math.PI * 2.0 * i / 20.0 + Math.PI / 20.0))
            - size / 2;
            g2d.fillOval(x, y, size, size);
        }
        
        if (debug)
        {
            drawDebugFirstCircleBalls(g2d, circleRadius, ballSize, firstCircleCenterX, firstCircleCenterY);
        }
        
        double secondCircleCenterX = firstCircleCenterX + circleRadius + circleRadius * (cutRadiusToNormalRadiusRatio)
        - circleRadius * (1.0 - cutRadiusToNormalRadiusRatio);
        double secondCircleCenterY = firstCircleCenterY;
        
        // drawing the R list
        for (int i = 13; i < 27; ++i)
        {
            g2d.setColor(board.getRightBalls().get(i - 13).getBallColor().color);
            int size = (int) ballSize;
            int x = (int) (secondCircleCenterX + circleRadius * Math.cos(Math.PI * 2.0 * i / 20.0 + Math.PI / 20.0))
            - size / 2;
            int y = (int) (secondCircleCenterY + circleRadius * Math.sin(Math.PI * 2.0 * i / 20.0 + Math.PI / 20.0))
            - size / 2;
            g2d.fillOval(x, y, size, size);
        }
        
        // drawing the Cb
        {
            g2d.setColor(board.getBottomCentralBall().getBallColor().color);
            int size = (int) ballSize;
            int x = (int) (secondCircleCenterX + circleRadius * Math.cos(Math.PI * 2.0 * 27 / 20.0 + Math.PI / 20.0))
            - size / 2;
            int y = (int) (secondCircleCenterY + circleRadius * Math.sin(Math.PI * 2.0 * 27 / 20.0 + Math.PI / 20.0))
            - size / 2;
            g2d.fillOval(x, y, size, size);
        }
        
        // drawing the l list
        for (int i = 28; i < 32; ++i)
        {
            g2d.setColor(board.getCenterLeftBalls().get(i - 28).getBallColor().color);
            int size = (int) ballSize;
            int x = (int) (secondCircleCenterX + circleRadius * Math.cos(Math.PI * 2.0 * i / 20.0 + Math.PI / 20.0))
            - size / 2;
            int y = (int) (secondCircleCenterY + circleRadius * Math.sin(Math.PI * 2.0 * i / 20.0 + Math.PI / 20.0))
            - size / 2;
            g2d.fillOval(x, y, size, size);
        }
        
        if (debug)
        {
            drawDebugSecondCircleBalls(g2d, circleRadius, ballSize, secondCircleCenterX, secondCircleCenterY);
        }
    }
    
    private void drawDebugSecondCircleBalls(Graphics2D g2d, double circleRadius, double ballSize,
    double secondCircleCenterX, double secondCircleCenterY)
    {
        g2d.setColor(Color.MAGENTA.darker());
        for (int i = 13; i < 32; ++i)
        {
            int size = (int) ballSize;
            int x = (int) (secondCircleCenterX + circleRadius * Math.cos(Math.PI * 2.0 * i / 20.0 + Math.PI / 20.0))
            - size / 2;
            int y = (int) (secondCircleCenterY + circleRadius * Math.sin(Math.PI * 2.0 * i / 20.0 + Math.PI / 20.0))
            - size / 2;
            g2d.drawRect(x, y, size, size);
            g2d.drawString("" + i, x, y);
        }
    }
    
    private void drawDebugFirstCircleBalls(Graphics2D g2d, double circleRadius, double ballSize,
    double firstCircleCenterX, double firstCircleCenterY)
    {
        g2d.setColor(Color.MAGENTA.darker());
        for (int i = 3; i < 22; ++i)
        {
            int size = (int) ballSize;
            int x = (int) (firstCircleCenterX + circleRadius * Math.cos(Math.PI * 2.0 * i / 20.0 + Math.PI / 20.0))
            - size / 2;
            int y = (int) (firstCircleCenterY + circleRadius * Math.sin(Math.PI * 2.0 * i / 20.0 + Math.PI / 20.0))
            - size / 2;
            g2d.drawOval(x, y, size, size);
            g2d.drawString("" + i, x, y);
        }
    }
    
    private void drawDebugMainCircles(Graphics2D g2d, double cutRadiusToNormalRadiusRatio, double maxCircleRadius,
    double circleRadius, int xStart, int yStart)
    {
        g2d.setColor(Color.MAGENTA.darker());
        
        int size = (int) (circleRadius * 2.0);
        // center of the image
        int xCenter = (int) (maxCircleRadius + maxCircleRadius * cutRadiusToNormalRadiusRatio);
        int yCenter = (int) maxCircleRadius;
        g2d.fillOval(xCenter - 3, yCenter - 3, 6, 6);
        
        g2d.drawOval(xStart, yStart, size, size);
        
        xStart = (int) (xStart + circleRadius + circleRadius * (cutRadiusToNormalRadiusRatio) - circleRadius
        * (1.0 - cutRadiusToNormalRadiusRatio));
        
        g2d.drawOval(xStart, yStart, size, size);
    }
    
    public static void main(String[] args)
    {
        JFrame f = new JFrame("Test component");
        f.add(new HungarianRingsComponent(new Board()));
        f.setPreferredSize(new Dimension(800, 800));
        f.setSize(new Dimension(800, 800));
        f.pack();
        // f.setExtendedState(JFrame.MAXIMIZED_BOTH);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
    }
    
    protected void setDebug(boolean debug)
    {
        this.debug = debug;
    }
    
}
